//package com.xueliman.iov.server.config;
//
//
//import com.nimbusds.jose.jwk.JWKSet;
//import com.nimbusds.jose.jwk.RSAKey;
//import com.nimbusds.jose.jwk.source.JWKSource;
//import com.nimbusds.jose.proc.SecurityContext;
//import com.xueliman.iov.server.other.ApplicationProperties;
//import com.xueliman.iov.server.util.JwksUtils;
//import lombok.RequiredArgsConstructor;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.Ordered;
//import org.springframework.core.annotation.Order;
//import org.springframework.jdbc.core.JdbcTemplate;
//import org.springframework.security.config.Customizer;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
//import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
//import org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer;
//import org.springframework.security.oauth2.core.AuthorizationGrantType;
//import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
//import org.springframework.security.oauth2.core.OAuth2TokenFormat;
//import org.springframework.security.oauth2.core.oidc.OidcScopes;
//import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
//import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationConsentService;
//import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
//import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
//import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
//import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
//import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
//import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
//import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
//import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
//import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
//import org.springframework.security.web.SecurityFilterChain;
//import org.springframework.security.web.util.matcher.RequestMatcher;
//import org.springframework.util.ObjectUtils;
//
//import java.time.Duration;
//
///**
// * @author zxg
// * 认证服务器配置
// */
//
//@RequiredArgsConstructor
//@Configuration(proxyBeanMethods = false)
//class AuthorizationServerConfiguration {
//    private final ApplicationProperties properties;
//
//    /**
//     * 自定义授权页面
//     */
//    private static final String CUSTOM_CONSENT_PAGE_URI = "/oauth2/consent";
//
//    /**
//     *
//     * 使用默认配置进行form表单登录
//     * OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)
//     */
//    @Bean
//    @Order(Ordered.HIGHEST_PRECEDENCE)
//    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
//        // TODO: 2022/4/22 一般此处进行个性化配置
//
//        // 使用默认security配置
//        OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();
//
//        //设置自定义授权页面
//        authorizationServerConfigurer.authorizationEndpoint(c-> c.consentPage(CUSTOM_CONSENT_PAGE_URI));
//
//        RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
//
//        http.requestMatcher(endpointsMatcher)
//                .authorizeRequests((authorizeRequests) -> authorizeRequests.anyRequest().authenticated())
//                .csrf((csrf) -> csrf.ignoringRequestMatchers(new RequestMatcher[]{endpointsMatcher}))
//                .apply(authorizationServerConfigurer);
//
//        return http.formLogin(Customizer.withDefaults()).build();
//    }
//
//    /**
//     * 注册客户端应用
//     */
//    @Bean
//    public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {
//        JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
//
//        //todo 个性化配置 生产的话，只初始化JdbcRegisteredClientRepository
//
//        //此处新建一个clientId = zxg的客户端
//        String clientId = "zxg";
//        RegisteredClient registeredClient = registeredClientRepository.findByClientId(clientId);
//        if (ObjectUtils.isEmpty(registeredClient)){
//            registeredClient = this.createRegisteredClient(clientId);
//            registeredClientRepository.save(registeredClient);
//        }
//
//        return registeredClientRepository;
//    }
//
//    /**
//     * 新建一个客户端配置项
//     */
//    private RegisteredClient createRegisteredClient(String clientId) {
//        return RegisteredClient.withId("1")
////                客户端ID和密码
//                .clientId(clientId)
////                PRIVATE_KEY_JWT 不需要这个  CLIENT_SECRET_JWT需要
//                .clientSecret("226ab006e9494b0e84893cd7b402cd8e")
////                名称 可不定义
//                .clientName("@zxg")
////                授权方法
//                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
//                // jwt 断言必备
//                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT)
//                .clientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT)
////                授权类型
//                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
//                .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
//                .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
////                回调地址名单，不在此列将被拒绝 而且只能使用IP或者域名  不能使用 localhost
////                .redirectUri("http://127.0.0.1:9001/authorized")
//                .redirectUri("https://www.baidu.com")
////                .redirectUri("http://127.0.0.1:9001/getTest")
////                OIDC支持
//                .scope(OidcScopes.OPENID)
////                其它Scope
//                .scope("message.read")
//                .scope("message.write")
////                JWT的配置项 包括TTL  是否复用refreshToken等等
//                .tokenSettings(TokenSettings.builder()
//                        //使用透明方式，默认是 OAuth2TokenFormat SELF_CONTAINED
////                        .accessTokenFormat(OAuth2TokenFormat.REFERENCE)
//                        // 授权码的有效期
//                        .accessTokenTimeToLive(Duration.ofHours(1))
//                        // 刷新token的有效期
//                        .refreshTokenTimeToLive(Duration.ofDays(3))
//                        .reuseRefreshTokens(true).build())
////                配置客户端相关的配置项，包括验证密钥或者 是否需要授权页面
//                .clientSettings(ClientSettings.builder()
////                        CLIENT_SECRET_JWT 采用HMAC SHA-256   注意区别于PRIVATE_KEY_JWT
//                        .requireAuthorizationConsent(true)
//                        .build())
//                .build();
//    }
//
//    /**
//     * 授权服务：管理OAuth2授权信息服务
//     */
//    @Bean
//    public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
//        return new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
//    }
//
//    /**
//     * 授权确认信息处理服务
//     */
//    @Bean
//    public OAuth2AuthorizationConsentService authorizationConsentService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
//        return new JdbcOAuth2AuthorizationConsentService(jdbcTemplate, registeredClientRepository);
//    }
//
//    /**
//     * 加载JWK资源
//     * JWT：指的是 JSON Web Token，不存在签名的JWT是不安全的，存在签名的JWT是不可窜改的
//     * JWS：指的是签过名的JWT，即拥有签名的JWT
//     * JWK：既然涉及到签名，就涉及到签名算法，对称加密还是非对称加密，那么就需要加密的 密钥或者公私钥对。此处我们将 JWT的密钥或者公私钥对统一称为 JSON WEB KEY，即 JWK。
//     */
//    @Bean
//    public JWKSource<SecurityContext> jwkSource() {
//        RSAKey rsaKey = JwksUtils.generateRsa();
//        JWKSet jwkSet = new JWKSet(rsaKey);
//        return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
//    }
//
//    /**
//     * 配置 OAuth2.0 提供者元信息
//     */
//    @Bean
//    public ProviderSettings providerSettings() {
//        return ProviderSettings.builder().issuer(properties.getSecurity().getOauth2().getIssuerUrl()).build();
//    }
//}
